package com.liusiqi.framework.context.support;

import com.liusiqi.framework.beans.BeanDefinition;
import com.liusiqi.framework.beans.MutablePropertyValues;
import com.liusiqi.framework.beans.PropertyValue;
import com.liusiqi.framework.beans.factory.support.BeanDefinitionRegistry;
import com.liusiqi.framework.beans.factory.xml.XmlBeanDefinitionReader;
import com.liusiqi.framework.utils.StringUtils;

import java.lang.reflect.Method;
import java.security.AlgorithmConstraints;

/**
 * @author: sql
 * @date: 2024/2/22
 * @Description:IOC容器具体的子实现类，加载XML配置文件
 * @version: 1.0
 */
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{
    public ClassPathXmlApplicationContext(String configLocation) {
        this.configLocation = configLocation;
        //指定具体的解析器对象
        this.beanDefinitionReader = new XmlBeanDefinitionReader();
        this.refresh();
    }

    @Override
    public Object getBean(String name) throws Exception{
        //判断容器中是否包含bean对象
        Object o = singletonObjects.get(name);
        if (o != null) {
            return o;
        }
        //获取BeanDefinition对象
        BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
        BeanDefinition beanDefinition = registry.getBeanDefinition(name);
        //反射创建bean对象
        String className = beanDefinition.getClassName();
        Class<?> aClass = Class.forName(className);
        Object beanObj = aClass.newInstance();
        //进行依赖注入
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues) {
            //获取property标签的属性
            String name1 = propertyValue.getName();
            String value = propertyValue.getValue();
            String ref = propertyValue.getRef();
            if (ref != null && !"".equals(ref)) {
                //获取依赖的bean对象
                Object bean = getBean(ref);
                String methodName = StringUtils.getSetterMethod(name1);
                Method[] methods = aClass.getMethods();
                for (Method method : methods) {
                    if (methodName.equals(method)) {
                        method.invoke(beanObj,bean);
                    }
                }
            }
            if (value != null && !"".equals(value)) {
                String methodName = StringUtils.getSetterMethod(name1);
                Method method = aClass.getMethod(methodName, String.class);
                method.invoke(beanObj, value);
            }
        }
        //将bean对象存入容器
        this.singletonObjects.put(name, beanObj);
        return beanObj;
    }

    @Override
    public <T> T getBean(String name, Class<? extends T> clazz) {
        Object bean = null;
        try {
            bean = getBean(name);
            if (bean == null) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return clazz.cast(bean);
    }
}
